package com.holly.unit.deform.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.holly.unit.deform.entity.DesignFormAuth;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 类描述: 表单数据工具类
 *
 * @author fxr
 * @version 1.0.0
 * @date 2022/4/7 9:51
 */
public class DeformAuthUtil {

    static {
        List<DesignFormAuth> list = new ArrayList<>();
        list.add(newButtonAuth("add", "新增"));
        list.add(newButtonAuth("import", "导入"));
        list.add(newButtonAuth("export", "导出"));
        list.add(newButtonAuth("superQuery", "高级查询"));
        list.add(newButtonAuth("batchAction", "批量操作"));
        list.add(newButtonAuth("customColumn", "自定义列"));
        list.add(newButtonAuth("detail", "查看"));
        list.add(newButtonAuth("edit", "编辑"));
        list.add(newButtonAuth("delete", "删除"));
        list.add(newButtonAuth("getUrl", "获取编辑地址"));
        BUTTON_AUTH_LIST = list;
    }

    public static final List<DesignFormAuth> BUTTON_AUTH_LIST;

    public static DesignFormAuth newButtonAuth(String authField, String authTitle) {
        DesignFormAuth auth = new DesignFormAuth();
        auth.setPermissionType("button");
        auth.setAuthField(authField);
        auth.setAuthTitle(authTitle);
        return auth;
    }

    /**
     * 获取新的按钮列表
     *
     * @return
     */
    public static List<DesignFormAuth> getNewButtonList() {
        return BUTTON_AUTH_LIST.stream().map(auth -> {
            DesignFormAuth temp = new DesignFormAuth();
            BeanUtil.copyProperties(auth, temp);
            return temp;
        }).collect(Collectors.toList());
    }

    /**
     * 合并按钮列表
     */
    public static List<DesignFormAuth> assignButtonList(List<DesignFormAuth> target, List<DesignFormAuth> source) {
        for (DesignFormAuth auth : target) {
            // 是否和数据库的数据匹配上了
            boolean findIt = false;
            for (DesignFormAuth dbAuth : source) {
                if (dbAuth.getAuthField().equals(auth.getAuthField())) {
                    findIt = true;
                    // 和数据库的数据匹配上了，就直接复制所有的属性
                    String title = auth.getAuthTitle();
                    BeanUtil.copyProperties(dbAuth, auth);
                    auth.setAuthTitle(title);
                    break;
                }
            }
            // 和数据库的数据没有匹配上，就创建一个临时的key
            if (!findIt) {
                // 凡是以 temp- 开头的按钮，都是数据库里没有的，需要 save 而不是 edit
                auth.setId("temp-" + auth.getAuthField());
                auth.setAuthScopeIsAll("Y");
                auth.setStatus(1);
            }
        }
        return target;
    }

    /**
     * 检查按钮权限
     *
     * @param auths
     * @param authUserInfo 包含用户信息、该用户的部门和角色信息
     * @return
     */
    public static JSONObject checkButtonsAuth(List<DesignFormAuth> auths, JSONObject authUserInfo) {
        JSONObject buttons = new JSONObject();
        for (DesignFormAuth buttonAuth : BUTTON_AUTH_LIST) {
            String buttonCode = buttonAuth.getAuthField();
            boolean pass = true;
            for (DesignFormAuth auth : auths) {
                if (buttonCode.equalsIgnoreCase(auth.getAuthField())) {
                    pass = checkOneDesformAuth(auth, authUserInfo);
                    break;
                }
            }
            buttons.put(buttonCode, pass);
        }
        return buttons;
    }

    /**
     * 通过用户信息，检测权限
     *
     * @param auth
     * @param authUserInfo
     * @return
     */
    public static boolean checkOneDesformAuth(DesignFormAuth auth, JSONObject authUserInfo) {
        /* 判断该用户是否被存在被控范围 */
        boolean userHasAuth = false;

        // 判断是否针对所有人授权
        if ("Y".equalsIgnoreCase(auth.getAuthScopeIsAll())) {
            userHasAuth = true;
        }

        // 判断用户名是否匹配
        if (!userHasAuth) {
            userHasAuth = checkUserAuth(auth, authUserInfo, userHasAuth);
        }

        // 判断部门是否匹配
        if (!userHasAuth) {
            userHasAuth = checkDepartAuth(auth, authUserInfo, userHasAuth);
        }

        // 判断角色是否匹配
        if (!userHasAuth) {
            userHasAuth = checkRoleAuth(auth, authUserInfo, userHasAuth);
        }

        // userHasAuth = true = 用户拥有该权限
        return userHasAuth;
    }

    private static boolean checkUserAuth(DesignFormAuth auth, JSONObject authUserInfo, boolean userHasAuth) {
        JSONObject userInfo = authUserInfo.getJSONObject("userInfo");
        JSONArray values = new JSONArray();
        values.add(userInfo.getString("username"));
        Boolean temp = hasValue(auth.getAuthScopeUsersVal(), values);
        return temp == null ? userHasAuth : temp;
    }

    private static boolean checkDepartAuth(DesignFormAuth auth, JSONObject authUserInfo, boolean userHasAuth) {
        JSONArray departs = authUserInfo.getJSONArray("departs");
        if (departs == null) {
            departs = new JSONArray();
        }
        Boolean temp = hasValue(auth.getAuthScopeDepartsVal(), departs);
        return temp == null ? userHasAuth : temp;
    }

    private static boolean checkRoleAuth(DesignFormAuth auth, JSONObject authUserInfo, boolean userHasAuth) {
        JSONArray roles = authUserInfo.getJSONArray("roles");
        if (roles == null) {
            roles = new JSONArray();
        }
        Boolean temp = hasValue(auth.getAuthScopeRolesVal(), roles);
        return temp == null ? userHasAuth : temp;
    }

    private static Boolean hasValue(String authItem, JSONArray values) {
        if (StrUtil.isNotBlank(authItem) && values.size() >= 1) {
            String[] scopes = authItem.split(",");
            for (String scope : scopes) {
                for (Object value : values) {
                    if (scope.equals(value.toString())) {
                        return true;
                    }
                }
            }
        }
        return null;
    }

}
